package com.liurong.quartz.util;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import com.liurong.quartz.util.annotation.Cron;
import com.liurong.quartz.util.annotation.JobBaseConfig;
import com.liurong.quartz.util.entity.JobEntity;
import com.liurong.quartz.util.properties.PropertiesFactoryBean;

/**
 * 启动所有的定时任务。 此java需要配置在spring的配置文件中
 * 
 * @author liurong
 *
 */
public class JobStartConfig implements ApplicationContextAware {
	/**
	 * 判断定时任务的状态：key:jobName, value:启动状态（1:启动中，2:暂停）
	 */
	public static final Map<String, JobEntity> jobNameMap = new ConcurrentHashMap<String, JobEntity>();

	public static Scheduler scheduler = null;

	private ApplicationContext applicationContext;

	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	public void init() throws Exception {
		System.out.println("-------------开始扫描定时任务--------------");

		// 获取所有实现了JobDetail的类的bean
		Map<String, JobDetailWork> beansOfType = applicationContext.getBeansOfType(JobDetailWork.class);

		JobDetailWork jobDetail = null;
		Class<? extends JobDetailWork> jobDetailClass = null;
		JobBaseConfig jobBaseConfigAnnotation = null;
		Method method = null;
		Cron cronAnnotation = null;
		JobEntity jobEntity = null;
		String cronValue = null;
		String cronValueKey = null;

		List<Trigger> triggers = new ArrayList<Trigger>();

		MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean = null;
		CronTriggerFactoryBean cronTriggerFactoryBean = null;
		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
		Properties properties = PropertiesFactoryBean.getProperties();

		Set<String> keySet = beansOfType.keySet();
		for (String bean : keySet) {
			// 获取bean对象
			jobDetail = beansOfType.get(bean);
			// 根据bean对象得到class对象
			jobDetailClass = jobDetail.getClass();
			// 获取class的JobBaseConfig注解
			jobBaseConfigAnnotation = jobDetailClass.getAnnotation(JobBaseConfig.class);
			// 如果没有获取到JobBaseConfig注解则直接返回
			if (jobBaseConfigAnnotation == null) {
				continue;
			}

			System.out.println("开始启动---" + jobBaseConfigAnnotation.remark() + ",该定时任务"
					+ (jobBaseConfigAnnotation.isDistribute() ? "是分布式的," : "不是分布式的,")
					+ (jobBaseConfigAnnotation.isHandStart() ? "可以手动执行" : "不可以手动执行"));

			// 获取work方法
			method = jobDetailClass.getMethod("work");
			if (method == null) {
				continue;
			}
			// 获取work方法上的注解
			cronAnnotation = method.getAnnotation(Cron.class);
			if (cronAnnotation == null) {
				continue;
			}

			methodInvokingJobDetailFactoryBean = new MethodInvokingJobDetailFactoryBean();
			methodInvokingJobDetailFactoryBean.setTargetObject(jobDetail);
			methodInvokingJobDetailFactoryBean.setTargetMethod("work");
			methodInvokingJobDetailFactoryBean.setName(bean);
			methodInvokingJobDetailFactoryBean.afterPropertiesSet();

			// *********************从spring的properties中加载job的配置***********开始
			cronValue = cronAnnotation.value();
			if (cronValue.startsWith("${") && cronValue.endsWith("}")) {
				cronValueKey = cronValue.substring(2, cronValue.length() - 1);
				cronValue = properties.getProperty(cronValueKey);
			}
			if (cronValue == null || cronValue == "") {
				System.out.println("cron配置有误============" + bean);
				return;
			}
			cronValue = cronValue.trim();
			// *********************从spring的properties中加载job的配置***********结束

			cronTriggerFactoryBean = new CronTriggerFactoryBean();
			cronTriggerFactoryBean.setCronExpression(cronValue);
			cronTriggerFactoryBean.setJobDetail(methodInvokingJobDetailFactoryBean.getObject());
			cronTriggerFactoryBean.setName(bean);
			cronTriggerFactoryBean.afterPropertiesSet();

			triggers.add(cronTriggerFactoryBean.getObject());

			// 封装job的相关参数
			jobEntity = new JobEntity();
			jobEntity.setCronStr(cronValue);
			jobEntity.setIsStart(1);
			jobEntity.setHandStart(jobBaseConfigAnnotation.isHandStart());
			jobNameMap.put(bean, jobEntity);
		}
		System.out.println("-------------结束扫描定时任务--------------");
		Trigger[] triggersArr = {};
		Trigger[] array = triggers.toArray(triggersArr);
		schedulerFactoryBean.setTriggers(array);
		schedulerFactoryBean.afterPropertiesSet();
		scheduler = schedulerFactoryBean.getScheduler();

		scheduler.start();
	}

	public void destory() {
		if (scheduler != null) {
			try {
				scheduler.shutdown();
			} catch (SchedulerException e) {

			}
		}
	}
}
